import {
    isProxy,
    reactive,
    Ref,
    toRaw,
} from 'vue'
import dayjs from 'dayjs'
import { Solar } from 'lunar-javascript'
import { ElMessage } from 'element-plus';

export const Message = (msg: string, t: 'success' | 'error' | 'warning' |'info' ='success') => {
    ElMessage({
        message:msg,
        type: t
    })
}

// 格式化时间戳，默认为精确到秒
export const formatDate = (timestamp: number, format = 'YYYY-MM-DD HH:mm:ss') => {
    if (!timestamp)
        return ''
    return dayjs(timestamp).format(format)
}

//根据时间戳获取星期几
export const getWeekByDate = (timestamp:number) => {
    const week = ['一','二','三','四','五','六','日']
    return week[dayjs(timestamp).day() - 1]
}

//根据时间戳获取农历日期
export const getLunarByDate = (timestamp: number) => {
    const date = new Date(timestamp)
    const solar = Solar.fromYmd(date.getFullYear(), date.getMonth() + 1, date.getUTCDate())
    return solar.getLunar().getMonthInChinese() + '月' + solar.getLunar().getDayInChinese()
}

// 深拷贝
export const deepCopy = (o: any): any => {
    // const o = isProxy(originObj) ? toRaw(originObj) : originObj
    if (isProxy(o)) {
        return deepCopy(toRaw(o))
    }
    else if (o instanceof Function) {
        return o
    }
    else if (Array.isArray(o)) {
        const array: Array<any> = []
        for (let i = 0; i < o.length; ++i)
            array[i] = deepCopy(o[i])

        return array
    }
    else if (o instanceof Date) {
        return new Date(o.valueOf())
    }
    else if (o instanceof Object) {
        const obj: any = {}
        for (const j in o)
            obj[j] = deepCopy(o[j])

        return obj
    }
    else {
        return o
    }
}

/**
 * 赋值响应式对象
 * @param originObj 原始对象
 * @param dataObj 数据对象
 * 注意不要使用该方法清空对象，清空整个对象请使用clearReactive
 */
export const setReactive = (originObj: Record<string, any> | {}, dataObj: Record<string, any>) => {
    const keys = Object.keys(dataObj || {})
    const oldKeys = Object.keys(originObj || {})
    if (keys.length > 0) {
        keys.forEach((key) => {
            const newVal = dataObj[key]
            if (typeof newVal === 'object' && newVal !== null && !Array.isArray(newVal)) {
                const obj = reactive({})

                setReactive(obj, newVal);
                (originObj as Record<string, any>)[key] = obj
            }
            else {
                (originObj as Record<string, any>)[key] = dataObj[key]
            }
            // ;(originObj as Record<string, any>)[key] = dataObj[key]
        })

        oldKeys.forEach((oKey) => {
            if (!keys.includes(oKey))
                delete (originObj as Record<string, any>)[oKey]
        })
    }
    else {
        originObj = reactive(dataObj)
    }
}

// 根据类型初始化值
export const initByValueType = (val: unknown) => {
    if (typeof val === 'string') {
        return ''
    }
    else if (typeof val === 'number') {
        return undefined
    }
    else if (typeof val === 'boolean') {
        return false
    }
    else if (typeof val === 'undefined') {
        return undefined
    }
    else if (val === null) {
        return null
    }
    else if (Array.isArray(val)) {
        return []
    }
    else if (typeof val === 'object') {
        for (const k in (val as Record<PropertyKey, string | number | boolean>))
            (val as any)[k] = initByValueType((val as Record<PropertyKey, string | number | boolean>)[k])

        return val
    }
    else {
        return undefined
    }
}

/**
 * 初始化响应式对象
 * @param dataObj 数据对象
 * @param keys 操作得key值
 * @param isDelete 是否为删除还是保留上面得keys值
 * 如果为false，那么对象只会剩下keys中得属性，并完成初始化
 */
export const initReactive = (dataObj: Record<string, any>, keys?: Array<keyof typeof dataObj>, isDelete = true) => {
    const dataObjKeys = Object.keys(dataObj || {})
    if (dataObjKeys.length > 0) {
        dataObjKeys.forEach((key) => {
            if (isDelete) {
                if (keys?.includes(key))
                    delete dataObj[key]
                else
                    dataObj[key] = initByValueType(dataObj[key])
                // dataObj[key] = ''
            }
            else {
                if (keys?.includes(key)) {
                    // dataObj[key] = ''
                    dataObj[key] = initByValueType(dataObj[key])
                }
                else {
                    delete dataObj[key]
                }
            }
        })
    }
}

// 生成随机字符串
export const uuid = (len: number, radix?: number) => {
    const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
    const uuid: string[] = []
    let i
    radix = radix || chars.length

    if (len) {
        // Compact form
        for (i = 0; i < len; i++) uuid[i] = chars[0 | (Math.random() * radix)]
    }
    else {
        // rfc4122, version 4 form
        let r

        // rfc4122 requires these characters
        uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
        uuid[14] = '4'

        // Fill in random data.  At i==19 set the high bits of clock sequence as
        // per rfc4122, sec. 4.1.5
        for (i = 0; i < 36; i++) {
            if (!uuid[i]) {
                r = 0 | (Math.random() * 16)
                uuid[i] = chars[i === 19 ? (r & 0x3) | 0x8 : r]
            }
        }
    }

    return uuid.join('')
}

//一键复制到剪切板
export const clickCopy = (copyData:string) => {
    const input = document.createElement('input')
    input.value = copyData
    document.body.appendChild(input)
    input.select()
    document.execCommand("Copy")
    document.body.removeChild(input)
}